package com.md.model.excel;

import com.md.util.ClassUtils;
import com.md.util.ExcelUtil;
import com.md.value.ConvertType;
import lombok.Data;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.FontUnderline;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRElt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.List;
import java.util.Optional;

import static com.md.util.ColorUtil.getBlackColorInfo;
import static com.md.value.UnitConstants.DPI;
import static com.md.value.UnitConstants.POINTS;

/**
 * @author 刘骄阳
 * 2024-05-14 1:54
 */
@Data
public class CellFontStyleInfo implements Cloneable {
  /**
   * 字体大小(单位: 点,pt)
   */
  private Double fontSize;
  /**
   * 字体颜色
   */
  private ExcelColorInfo color;

  /**
   * 字体名称
   */
  private String fontName;

  /**
   * 下划线
   */
  private FontUnderline underline;
  /**
   * 是否倾斜
   */
  private Boolean isItalic;
  /**
   * 是否加粗
   */
  private Boolean isBold;

  /**
   * 是否有删除线
   */
  private Boolean isStrikeOut;

  /**
   * 纯文本内容
   */
  private String content;

  public static CellFontStyleInfo readFontStyle(final XSSFCell cell,
                                                final StylesTable stylesTable) {
    XSSFCellStyle cellStyle = cell.getCellStyle();
    XSSFFont font = cellStyle.getFont();
    CellFontStyleInfo cellFontStyleInfo = new CellFontStyleInfo();

    // 解析颜色
    ExcelColorInfo excelColorInfo = ExcelColorInfo.getColorInfo(font, stylesTable);
    cellFontStyleInfo.setColor(excelColorInfo);

    // 获取字体大小
    cellFontStyleInfo.setFontSize((double) font.getFontHeightInPoints());

    // 获取字体名称
    cellFontStyleInfo.setFontName(font.getFontName());

    // 是否有加粗
    cellFontStyleInfo.setIsBold(font.getBold());

    // 是否有倾斜
    cellFontStyleInfo.setIsItalic(font.getItalic());
    // 删除线
    cellFontStyleInfo.setIsStrikeOut(font.getStrikeout());
    // 下划线
    cellFontStyleInfo.setUnderline(FontUnderline.valueOf(font.getUnderline()));

    // 文本内容
    cellFontStyleInfo.setContent(ExcelUtil.getCellValue(cell));
    return cellFontStyleInfo;
  }

  public static List<CellFontStyleInfo> readFontStyle(final XSSFRichTextString richText,
                                                      final StylesTable stylesTable,
                                                      final CellFontStyleInfo defaultCellFontStyleInfo) {
    List<CellFontStyleInfo> list = Lists.newArrayList();
    CTRst ctRst = richText.getCTRst();
    // 获取富文本字符串中的每个部分
    List<CTRElt> rList = ctRst.getRList();
    if (rList == null || rList.isEmpty()) {
      return list;
    }
    rList.forEach(ctrElt -> {
      CTRPrElt rPre = ctrElt.getRPr();
      if (rPre == null) {
        // 第一个肯定为空, 所以需要应用整个excel文档的样式
        CellFontStyleInfo cellFontStyleInfo = ClassUtils.source2Target(defaultCellFontStyleInfo,
          CellFontStyleInfo.class);
        cellFontStyleInfo.setContent(ctrElt.getT());
        list.add(cellFontStyleInfo);
        return;
      }

      CellFontStyleInfo cellFontStyleInfo = new CellFontStyleInfo();
      cellFontStyleInfo.setContent(ctrElt.getT());
      Optional.ofNullable(rPre.getColorList()).ifPresent(ctColors -> {
          if (ctColors.isEmpty()) {
            // 说明当前字体没有设置颜色
            cellFontStyleInfo.setColor(getBlackColorInfo(ExcelColorInfo.class));
            return;
          }
          cellFontStyleInfo.setColor(ExcelColorInfo.getColorInfo(ctColors.get(0), stylesTable));
        }
      );
      // 字体名称
      Optional.ofNullable(rPre.getRFontList()).ifPresent(rFonts ->
        cellFontStyleInfo.setFontName(rFonts.get(0).getVal())
      );
      // 是否倾斜
      Optional.ofNullable(rPre.getIList()).ifPresent(iLists ->
        cellFontStyleInfo.setIsItalic(!iLists.isEmpty() && iLists.get(0).getVal())
      );
      // 是否加粗
      Optional.ofNullable(rPre.getBList()).ifPresent(bLists ->
        cellFontStyleInfo.setIsBold(!bLists.isEmpty() && bLists.get(0).getVal())
      );
      // 字体大小
      Optional.ofNullable(rPre.getSzList()).ifPresent(sizes -> {
          if (sizes.isEmpty()) {
            return;
          }
          cellFontStyleInfo.setFontSize(sizes.get(0).getVal());
        }
      );
      // 下划线
      Optional.ofNullable(rPre.getUList()).ifPresent(cTUnderlineProperty -> {
          if (cTUnderlineProperty.isEmpty()) {
            cellFontStyleInfo.setUnderline(FontUnderline.NONE);
            return;
          }
          cellFontStyleInfo.setUnderline(FontUnderline.valueOf(cTUnderlineProperty.get(0).getVal().intValue()));
        }
      );
      // 删除线
      Optional.ofNullable(rPre.getStrikeList()).ifPresent(ctBooleanProperties ->
        cellFontStyleInfo.setIsStrikeOut(!ctBooleanProperties.isEmpty() && ctBooleanProperties.get(0).getVal())
      );
      list.add(cellFontStyleInfo);
    });
    return list;
  }

  /**
   * 获取真实的字体大小
   *
   * @return 字体大小
   */
  public BigDecimal getFormatFontSize(final ConvertType convertType) {
    switch (convertType) {
      case EXCEL_TO_HTML:
        return BigDecimal.valueOf(fontSize).divide(POINTS, MathContext.DECIMAL128).multiply(DPI)
          .setScale(2, RoundingMode.HALF_DOWN);
      default:
        break;
    }
    return null;
  }

  /**
   * 是否含有下划线
   *
   * @return 是否含有(true : 含有 ; false : 不含有)
   */
  public boolean getIsUnderLine() {
    return underline != null && underline != FontUnderline.NONE;
  }

  /**
   * 是否有设置颜色
   *
   * @return 是否设置(true : 有设置 ; false : 未设置)
   */
  public boolean getIsColor() {
    return color != null && color.getColor() != null;
  }

  @Override
  public CellFontStyleInfo clone() {
    try {
      return (CellFontStyleInfo) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError("Clone should be supported.", e);
    }
  }
}
